﻿using DependencyAnalysis.Algorithms.SubstringDetection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTests
{
    [TestClass]
    public class GeneralizedSuffixTreeTest
    {
        [TestMethod]
        public void WhenTreesHaveCommonSubstringReturnCorrectLength()
        {
            char[] text1 = "worst case scenario".ToCharArray();
            char[] text2 = "englands worst driver".ToCharArray();
            var tree = new GeneralizedSuffixTree(new[] { text1, text2 });
            var commonSubstr = tree.FindLongestCommonSubstring();
            Assert.AreEqual(6, commonSubstr.Length);
        }

        [TestMethod]
        public void WhenTreesHaveCommonSubstringReturnCorrectIndices()
        {
            char[] text1 = "englands worst driver".ToCharArray();
            char[] text2 = "worst case scenario".ToCharArray();
            var tree = new GeneralizedSuffixTree(new[] { text1, text2 });
            var commonSubstr = tree.FindLongestCommonSubstring();
            Assert.AreEqual(9, commonSubstr.BeginIndices[0]);
            Assert.AreEqual(0, commonSubstr.BeginIndices[1]);
        }

        [TestMethod]
        public void WhenSomeTreesHaveCommonSubstringReturnNumberOfDuplicates()
        {
            var texts = GetThreeTexts();
            var tree = new GeneralizedSuffixTree(texts);
            var commonSubstr = tree.FindCommonSubstrings(6);
            Assert.AreEqual(1, commonSubstr.Count);
        }

        private static char[][] GetThreeTexts()
        {
            char[][] texts = new[]
                {
                    "englands worst driver".ToCharArray(),
                    "worst case scenario".ToCharArray(),
                    "hullabalooza".ToCharArray()
                };
            return texts;
        }

        [TestMethod]
        public void WhenSomeTreesHaveCommonSubstringReturnOnlyLongestDuplicate()
        {
            var texts = GetThreeTexts();
            var tree = new GeneralizedSuffixTree(texts);
            var commonSubstr = tree.FindCommonSubstrings(5);
            Assert.AreEqual(1, commonSubstr.Count);
        }

        [TestMethod]
        public void WhenSomeTreesHaveCommonSubstringReturnCorrectIndices()
        {
            var texts = GetThreeTexts();
            var tree = new GeneralizedSuffixTree(texts);
            var commonSubstr = tree.FindCommonSubstrings(5);
            Assert.AreEqual(9, commonSubstr[0].BeginIndices[0]);
            Assert.AreEqual(0, commonSubstr[0].BeginIndices[1]);
        }

        private static char[][] GetFiveTexts()
        {
            char[][] texts = new[]
                {
                    "The primary goal when managing such resources is quite simply to make use of them in the most efficient manner.".ToCharArray(),
                    "This section documents the recommended pattern for implementing both explicit and implicit resource cleanup.".ToCharArray(),
                    "This is especially important when resources are limited, e.g. when only a limited quantity is available.".ToCharArray(),
                    "Managed types must occasionally encapsulate control over resources that are not managed by the CLR.".ToCharArray(),
                    "In fact, implementing finalizers by hand is seldom necessary thanks to the introduction of this type in the .NET Framework 2.0.".ToCharArray()
                };
            return texts;
        }

        [TestMethod]
        public void WhenMultipleCommonSubstringsReturnCorrectNumber()
        {
            var texts = GetFiveTexts();
            var tree = new GeneralizedSuffixTree(texts);
            var commonSubstr = tree.FindCommonSubstrings(7);
            Assert.AreEqual(4, commonSubstr.Count);
        }

        [TestMethod]
        public void WhenFindingCommonSubstringsReturnCorrectTextIndices()
        {
            var texts = GetFiveTexts();
            var tree = new GeneralizedSuffixTree(texts);
            var commonSubstr = tree.FindCommonSubstrings(13);
            Assert.AreEqual(1, commonSubstr[0].TextIndices[0]);
            Assert.AreEqual(4, commonSubstr[0].TextIndices[1]);
        }

        [TestMethod]
        public void WhenTwoTextsStartWithCommonSubstringThenReturnCorrectIndices()
        {
            char[] text0 = "hello world.".ToCharArray(); 
            char[] text1 = "worst driver englands.".ToCharArray();
            char[] text2 = "worst case scenario".ToCharArray();
            var tree = new GeneralizedSuffixTree(new[] { text0, text1, text2 });
            var commonSubstr = tree.FindCommonSubstrings(5);
            Assert.AreEqual(0, commonSubstr[0].BeginIndices[0]);
            Assert.AreEqual(0, commonSubstr[0].BeginIndices[1]);
        }
    }
}
